﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Threading;
using Microsoft.Devices;

namespace Pomodoro
{
    public partial class Wheel : UserControl
    {
        internal TimeScale TimeScale { get; set; }
        private DispatcherTimer _timer;

        private int _minutes = 25;
        private int _pixelsperminute = 40;
        //private double _pixelspersecond = 40 / 60;
        //private int _timescaleoffset = 210;
        private double _offset = 0;
        private bool _isdragging = true;
        private double _lasttick = 0;
        private double _secondsinterval = 1;


        /// <summary>
        /// Scrollable wheel with time scale and sounds.
        /// Rewinds back and throws an WheelStopped event if time is up.
        /// </summary>
        public Wheel()
        {
            InitializeComponent();
            InitializeTimer();
            HookEventHandlers();
            this.TimeScale = new TimeScale(this.Canvas, 180, 240, _pixelsperminute, _minutes);
        }

        /// <summary>
        /// Sets up the timer and time handler for rewinding the wheel.
        /// Quick 'n dirty, should decouple.
        /// </summary>
        private void InitializeTimer()
        {
            // TODO: timer op nieuwe waarde zetten.
            // timer zit in wheel en doet niets meer dan terugtikken Scroller.ScrollToHorizontalOffset tot 0.
            // Bij 0 een event gooien.

            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromSeconds(_secondsinterval);
            _timer.Tick += (s, e) =>
            {
                if (!_isdragging)
                {
                    _offset = _offset - (_pixelsperminute * (_secondsinterval / 60));
                    if (_offset <= 0)
                    {
                        StopWheel();
                    }
                    Scroller.ScrollToHorizontalOffset(_offset);
                }
            };
        }
                
        /// <summary>
        /// Binds event handlers for the wheel scrolling. Handles audio passing minute ticks.
        /// Quick 'n dirty, should decouple.
        /// </summary>
        private void HookEventHandlers()
        {
            // do not hook handlers if previewing XAML.
            if (DesignerProperties.IsInDesignTool) return;

            // Detect user dragging the wheel.
            Scroller.MouseEnter += (s, e) => { _isdragging = true; };
            Scroller.LostMouseCapture += (s, e) => { _isdragging = false; };

 	        // Listener reads scroller movements.
            var binding = new Binding("HorizontalOffset") { Source = Scroller };
            var listener = DependencyProperty.RegisterAttached("ListenerOffset", typeof(object), typeof(UserControl), new PropertyMetadata(delegate(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                // Detect the wheel passing minute ticks.
                double newoffset = _offset = (double)e.NewValue;
                int tickspassed = Math.Abs(Convert.ToInt32(Math.Floor((newoffset - _lasttick) / _pixelsperminute)));
                if (tickspassed > 0)
                {
                    // Play a sound for each minute tick.
                    Helpers.Sound.PlaySound(tickspassed, "Sounds/WheelTick.wav");

                    // Remember the last minute tick the wheel passed.
                    double modulus = newoffset % _pixelsperminute;
                    _lasttick = newoffset - modulus;

                    // Make sure the timer is running, so it can rewind.
                    _timer.Start();
                }

                // Test if wheel was rewinded by hand.
                if (newoffset == 0) StopWheel();
            }));
            Scroller.SetBinding(listener, binding);
        }

        private void StopWheel()
        {
            if (_timer.IsEnabled)
            {
                Helpers.Sound.PlaySound("Sounds/WheelStopped.wav");
                if (App.ViewModel.Vibrate)
                {
                    var vc = VibrateController.Default;
                    vc.Start(TimeSpan.FromMilliseconds(800));
                }
            }
            _timer.Stop();
            _offset = _lasttick = 0;
        }

        internal void WindUpWheel()
        {
            Scroller.ScrollToHorizontalOffset(_offset = _lasttick = _pixelsperminute * _minutes);
            _timer.Start();
            _isdragging = false;

            if (App.ViewModel.Vibrate)
            {
                var vc = VibrateController.Default;
                vc.Start(TimeSpan.FromMilliseconds(5));
            }
        }
    }
}
